package com.bood.shimmer.common.service.impl;

import cn.hutool.core.util.IdUtil;
import com.bood.shimmer.common.constant.ShimmerConstants;
import com.bood.shimmer.common.enums.BizExceptionEnum;
import com.bood.shimmer.common.exception.BizException;
import com.bood.shimmer.common.service.RedisService;
import com.bood.shimmer.common.service.TokenService;
import com.bood.shimmer.common.utils.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.StringJoiner;

/**
 * token 的服务实现类：token 引用了 Redis 服务，创建 token 采用随机算法工具类生成 随机 uuid 字符串,然后放入到 Redis 中
 * (为了防止数据的冗余保留,这里设置过期时间为1秒,具体可视业务而定)，如果放入成功，最后返回这个 token 值。
 * checkToken 方法就是从 header 中获取 token 到值(如果 header 中拿不到，就从 paramter 中获取)，如若不存在,直接抛出异常。
 * 这个异常信息可以被拦截器捕捉到，然后返回给前端。
 *
 * @author：bood
 * @since：2020/7/11
 */
@Service
public class TokenServiceImpl implements TokenService {

    @Resource
    private RedisService redisService;


    /**
     * <p>
     * 创建 token
     * </p>
     *
     * @return：java.lang.String
     * @author：bood
     * @date：2020/9/25
     */
    @Override
    public String createToken() {
        // 构造 idempotent_token
        StringJoiner stringJoiner = new StringJoiner("-");
        stringJoiner.add(ShimmerConstants.IDEMPOTENT_TOKEN)
                .add(IdUtil.simpleUUID());
        // 设置存入 Redis 的 Key
        String token = String.valueOf(stringJoiner);
        // 存储 token 到 Redis，且设置过期时间为3秒
        redisService.set(token, token, 3L);
        return token;
    }


    /**
     * <p>
     * 检验 token
     * </p>
     *
     * @param request:
     * @return：boolean
     * @author：bood
     * @date：2020/9/25
     */
    @Override
    public boolean checkToken(HttpServletRequest request) throws Exception {
        String token = request.getHeader(ShimmerConstants.IDEMPOTENT_TOKEN);

        // header 中不存在 token
        if (StringUtils.isBlank(token)) {
            token = request.getParameter(ShimmerConstants.IDEMPOTENT_TOKEN);

            // parameter 中也不存在 token
            if (StringUtils.isBlank(token)) {
                throw new BizException(BizExceptionEnum.ILLEGAL_ARGUME.message(), BizExceptionEnum.ILLEGAL_ARGUME.code());
            }

        }
        // Redis 中也不存在或者删除失败
        if (!redisService.hasKey(token) || !redisService.del(token)) {
            throw new BizException(BizExceptionEnum.REPETITIVE_OPERATION.message(), BizExceptionEnum.REPETITIVE_OPERATION.code());
        }

        return true;
    }

}
